/**
 * HTTP 请求工具类
 * 基于 Fetch API 封装，提供完整的请求拦截、响应拦截、错误处理等功能
 */

// 默认配置
const defaultConfig = {
  baseURL: '',
  timeout: 30000,
  headers: {
    'Content-Type': 'application/json'
  }
}

// 请求拦截器列表
const requestInterceptors = []
// 响应拦截器列表
const responseInterceptors = []

/**
 * 创建请求实例
 */
class Request {
  constructor(config = {}) {
    this.config = { ...defaultConfig, ...config }
  }

  /**
   * 添加请求拦截器
   * @param {Function} fulfilled - 成功回调
   * @param {Function} rejected - 失败回调
   */
  static addRequestInterceptor(fulfilled, rejected) {
    requestInterceptors.push({ fulfilled, rejected })
  }

  /**
   * 添加响应拦截器
   * @param {Function} fulfilled - 成功回调
   * @param {Function} rejected - 失败回调
   */
  static addResponseInterceptor(fulfilled, rejected) {
    responseInterceptors.push({ fulfilled, rejected })
  }

  /**
   * 处理请求拦截器
   */
  async processRequestInterceptors(config) {
    let processedConfig = config
    for (const interceptor of requestInterceptors) {
      if (interceptor.fulfilled) {
        try {
          processedConfig = await interceptor.fulfilled(processedConfig)
        } catch (error) {
          if (interceptor.rejected) {
            return interceptor.rejected(error)
          }
          throw error
        }
      }
    }
    return processedConfig
  }

  /**
   * 处理响应拦截器
   */
  async processResponseInterceptors(response) {
    let processedResponse = response
    for (const interceptor of responseInterceptors) {
      if (interceptor.fulfilled) {
        try {
          processedResponse = await interceptor.fulfilled(processedResponse)
        } catch (error) {
          if (interceptor.rejected) {
            return interceptor.rejected(error)
          }
          throw error
        }
      }
    }
    return processedResponse
  }

  /**
   * 构建完整的 URL
   */
  buildURL(url, params) {
    const fullURL = url.startsWith('http') ? url : `${this.config.baseURL}${url}`
    
    if (!params) return fullURL
    
    const queryString = Object.keys(params)
      .filter(key => params[key] !== undefined && params[key] !== null)
      .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
      .join('&')
    
    return queryString ? `${fullURL}?${queryString}` : fullURL
  }

  /**
   * 处理请求体
   */
  processRequestBody(data, headers) {
    const contentType = headers['Content-Type'] || headers['content-type']
    
    if (!data) return null
    
    if (contentType.includes('application/json')) {
      return JSON.stringify(data)
    }
    
    if (contentType.includes('application/x-www-form-urlencoded')) {
      return Object.keys(data)
        .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
        .join('&')
    }
    
    if (data instanceof FormData) {
      delete headers['Content-Type'] // 让浏览器自动设置
      return data
    }
    
    return data
  }

  /**
   * 处理响应
   */
  async processResponse(response) {
    const contentType = response.headers.get('content-type')
    
    if (contentType && contentType.includes('application/json')) {
      return await response.json()
    }
    
    if (contentType && contentType.includes('text/')) {
      return await response.text()
    }
    
    if (contentType && contentType.includes('blob')) {
      return await response.blob()
    }
    
    return await response.text()
  }

  /**
   * 发送请求
   */
  async request(url, options = {}) {
    // 合并配置
    let config = {
      ...this.config,
      ...options,
      headers: {
        ...this.config.headers,
        ...options.headers
      }
    }

    // 处理请求拦截器
    config = await this.processRequestInterceptors(config)

    // 构建 URL
    const fullURL = this.buildURL(url, config.params)

    // 处理请求体
    const body = this.processRequestBody(config.data, config.headers)

    // 创建 AbortController 用于超时控制
    const controller = new AbortController()
    const timeoutId = setTimeout(() => controller.abort(), config.timeout)

    try {
      // 发送请求
      const response = await fetch(fullURL, {
        method: config.method || 'GET',
        headers: config.headers,
        body: body,
        signal: controller.signal,
        ...config
      })

      clearTimeout(timeoutId)

      // 检查响应状态
      if (!response.ok) {
        throw new Error(`HTTP Error: ${response.status} ${response.statusText}`)
      }

      // 处理响应数据
      const data = await this.processResponse(response)

      // 构建响应对象
      const result = {
        data,
        status: response.status,
        statusText: response.statusText,
        headers: response.headers,
        config
      }

      // 处理响应拦截器
      return await this.processResponseInterceptors(result)

    } catch (error) {
      clearTimeout(timeoutId)

      // 处理超时错误
      if (error.name === 'AbortError') {
        throw new Error('Request timeout')
      }

      // 处理响应拦截器的错误回调
      for (const interceptor of responseInterceptors) {
        if (interceptor.rejected) {
          try {
            return await interceptor.rejected(error)
          } catch (e) {
            // 继续抛出错误
          }
        }
      }

      throw error
    }
  }

  /**
   * GET 请求
   */
  get(url, config = {}) {
    return this.request(url, { ...config, method: 'GET' })
  }

  /**
   * POST 请求
   */
  post(url, data, config = {}) {
    return this.request(url, { ...config, method: 'POST', data })
  }

  /**
   * PUT 请求
   */
  put(url, data, config = {}) {
    return this.request(url, { ...config, method: 'PUT', data })
  }

  /**
   * DELETE 请求
   */
  delete(url, config = {}) {
    return this.request(url, { ...config, method: 'DELETE' })
  }

  /**
   * PATCH 请求
   */
  patch(url, data, config = {}) {
    return this.request(url, { ...config, method: 'PATCH', data })
  }

  /**
   * 上传文件
   */
  upload(url, file, config = {}) {
    const formData = new FormData()
    
    if (file instanceof File) {
      formData.append('file', file)
    } else if (file instanceof FileList) {
      Array.from(file).forEach((f, index) => {
        formData.append(`file${index}`, f)
      })
    } else if (typeof file === 'object') {
      Object.keys(file).forEach(key => {
        formData.append(key, file[key])
      })
    }

    return this.request(url, {
      ...config,
      method: 'POST',
      data: formData
    })
  }

  /**
   * 下载文件
   */
  async download(url, filename, config = {}) {
    const response = await this.request(url, {
      ...config,
      headers: {
        ...config.headers,
        'Content-Type': 'application/octet-stream'
      }
    })

    // 创建下载链接
    const blob = new Blob([response.data])
    const link = document.createElement('a')
    link.href = window.URL.createObjectURL(blob)
    link.download = filename || 'download'
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
    window.URL.revokeObjectURL(link.href)

    return response
  }
}

// 创建默认实例
const request = new Request()

// 导出实例和类
export default request
export { Request }

